package com.dd.cloud.user.service.doctor.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.SmsConstants;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.entity.doctor.DoctorEquity;
import com.dd.cloud.user.entity.doctor.DoctorUser;
import com.dd.cloud.user.entity.order.OrderPay;
import com.dd.cloud.user.entity.pres.PresPrescription;
import com.dd.cloud.user.entity.product.ProductGiveRule;
import com.dd.cloud.user.entity.product.ProductUseRecord;
import com.dd.cloud.user.mapper.doctor.DoctorEquityMapper;
import com.dd.cloud.user.mq.MQConfig;
import com.dd.cloud.user.mq.RabbitSend;
import com.dd.cloud.user.res.doctor.DoctorEquityDetailRes;
import com.dd.cloud.user.service.doctor.IDoctorEquityService;
import com.dd.cloud.user.service.doctor.IDoctorUserService;
import com.dd.cloud.user.service.pres.IPresPrescriptionService;
import com.dd.cloud.user.service.product.IProductGiveRuleService;
import com.dd.cloud.user.service.product.IProductUseRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Lx
 * @version 1.0
 * @date 2024/2/2
 */
@Slf4j
@Service
public class DoctorEquityServiceImpl extends ServiceImpl<DoctorEquityMapper, DoctorEquity> implements IDoctorEquityService {
    @Autowired
    private RabbitSend rabbitSend;
    @Autowired
    private IProductUseRecordService productUseRecordService;
    @Autowired
    private IPresPrescriptionService presPrescriptionService;
    @Autowired
    private IDoctorEquityService doctorEquityService;
    @Autowired
    private IProductGiveRuleService productGiveRuleService;

    /**
     * 查询医生账号权益
     *
     * @return
     */
    @Override
    public DoctorEquityDetailRes queryDoctorEquityDetail() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        return queryDoctorEquityDetail(loginInfo.getId());
    }

    /**
     * 查询医生账号权益
     *
     * @param doctorId
     * @return
     */
    @Override
    public DoctorEquityDetailRes queryDoctorEquityDetail(Integer doctorId) {
        if (doctorId == null) {
            throw new ZekeException(400, "医生id不能为空");
        }
        DoctorEquityDetailRes res = getBaseMapper().queryDoctorEquityDetail(doctorId);
        if (res == null) {
            return new DoctorEquityDetailRes();
        }
        res.setAccumulateDay(res.getAccumulateDay() == null ? 0 : res.getAccumulateDay());
        res.setAccumulateFee(res.getAccumulateFee() == null ? 0 : res.getAccumulateFee());
        QueryWrapper<ProductUseRecord> qw = new QueryWrapper<>();
        qw.lambda().eq(ProductUseRecord::getDoctorId, doctorId);
        qw.lambda().eq(ProductUseRecord::getType, 1);
        res.setAiCount(productUseRecordService.count(qw));
        qw.clear();
        qw.lambda().eq(ProductUseRecord::getDoctorId, doctorId);
        qw.lambda().eq(ProductUseRecord::getType, 2);
        res.setKcCount(productUseRecordService.count(qw));
        res.setScantFee((res.getAiCount() * 5 + res.getKcCount() * 10) * 100 - res.getAccumulateFee());
        return res;
    }

    /**
     * 慈善账号免费权益失效提醒
     */
    @Override
    public void csAccountExpireRemindSms() {
        List<DoctorEquity> list = getBaseMapper().queryCsAccount();
        for (DoctorEquity item : list) {
            Duration duration = Duration.between(item.getCreateDate(), item.getExpirDate());
            long day1 = duration.toDays();
            duration = Duration.between(item.getCreateDate(), LocalDateTime.now());
            long day2 = duration.toDays();
            long day3 = day1 / 3;
            long day4 = day1 / 2;
            if (day2 == day3) {
                Map<String, String> msg = new HashMap<>(5);
                msg.put("phone", item.getPhone());
                msg.put("day", String.valueOf(day3));
                msg.put("use", String.valueOf(day4 - day3));
                msg.put("param_type", SmsConstants.ParamType.JSON);
                msg.put("sms_template", SmsConstants.Template.CS_ACCOUNT_NO_USE);
                rabbitSend.sendMessage(MQConfig.SMS_EXCHANGE, MQConfig.SMS_KEY, msg);
            }
            if (day2 == day4) {
                Map<String, String> msg = new HashMap<>(4);
                msg.put("phone", item.getPhone());
                msg.put("day", String.valueOf(day4));
                msg.put("param_type", SmsConstants.ParamType.JSON);
                msg.put("sms_template", SmsConstants.Template.CS_ACCOUNT_EXPIRE);
                rabbitSend.sendMessage(MQConfig.SMS_EXCHANGE, MQConfig.SMS_KEY, msg);
            }
        }
    }

    @Autowired
    private IDoctorUserService doctorUserService;

    @Override
    public void csDoctorAccountRemind() {
        List<DoctorEquity> list = getBaseMapper().queryCsAccount();
        List<DoctorUser> doctorUserList = new ArrayList<>();
        for (DoctorEquity item : list) {
            Duration duration = Duration.between(item.getCreateDate(), item.getExpirDate());
            long day1 = duration.toDays();
            duration = Duration.between(item.getCreateDate(), LocalDateTime.now());
            long day2 = duration.toDays();
            long day4 = day1 / 2;
            if (day2 == day4) {
                Integer doctorId = item.getDoctorId();
                DoctorUser doctorUser = new DoctorUser();
                doctorUser.setIsCertification(0).setId(doctorId);
                doctorUserList.add(doctorUser);
            }
        }
        if (CollectionUtil.isNotEmpty(doctorUserList)) {
            doctorUserService.updateBatchById(doctorUserList);
        }
    }


    @Override
    public void refundTime(OrderPay orderPay) {
        String serverNo = orderPay.getServerNo();
        PresPrescription presPrescription = presPrescriptionService.getById(serverNo);
        if (presPrescription == null) {
            return;
        }
        Integer doctorUserType = doctorUserService.getDoctorUserType(presPrescription.getDoctorId());
        if (doctorUserType != 2) {
            return;
        }
        LambdaQueryWrapper<DoctorEquity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DoctorEquity::getType, 2)
                .eq(DoctorEquity::getDoctorId, presPrescription.getDoctorId());
        DoctorEquity doctorEquity = doctorEquityService.getOne(queryWrapper);
        if (doctorEquity == null) {
            return;
        }
        LocalDateTime startDate = doctorEquity.getStartDate();
        LocalDateTime endDate = doctorEquity.getEndDate();
        if (startDate != null
                && LocalDateTime.now().isAfter(startDate)
                && LocalDateTime.now().isBefore(endDate)) {
            Integer csOrderNum = doctorEquity.getCsOrderNum();
            log.info("当前类型订单数量:{}", csOrderNum);
            if (csOrderNum > 0) {
                csOrderNum = csOrderNum - 1;
                doctorEquity.setOrderNum(csOrderNum);
//            } else if (csOrderNum == 0 && doctorEquity.getIsReach() == 1) {
//                log.info("~已经产生兑换了时间~时间扣减");
//                Integer totalNum = doctorEquity.getOrderNum();
//                log.info("~上次扣减数量~:{}", totalNum);
//                doctorEquity.setCsOrderNum(totalNum - 1);
//                Integer accumulateDay = doctorEquity.getAccumulateDay();
//                Integer orderDay = doctorEquity.getOrderDay();
//                log.info("~上次累加天数:{}", orderDay);
//                log.info("总的累加天数:{}", accumulateDay);
//                if (accumulateDay >= orderDay) {
//                    doctorEquity.setAccumulateDay(accumulateDay - orderDay);
//                }
//                LocalDateTime expirDate = doctorEquity.getExpirDate();
//                doctorEquity.setExpirDate(expirDate.plusDays(-orderDay)).setIsReach(0);
//                doctorEquityService.updateById(doctorEquity);
//            }
            }
        }

    }

    @Override
    public void saveDoctorEquity(OrderPay orderPay, Integer type) {
        String serverNo = orderPay.getServerNo();
        PresPrescription presPrescription = presPrescriptionService.getById(serverNo);
        if (presPrescription == null) {
            return;
        }
        Integer doctorUserType = doctorUserService.getDoctorUserType(presPrescription.getDoctorId());
        if (doctorUserType != 2) {
            log.info("该账号不是慈善账号");
            return;
        }
        LambdaQueryWrapper<DoctorEquity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DoctorEquity::getType, 2)
                .eq(DoctorEquity::getDoctorId, presPrescription.getDoctorId());
        DoctorEquity doctorEquity = doctorEquityService.getOne(queryWrapper);
        if (doctorEquity != null) {
            LocalDateTime startDate = doctorEquity.getStartDate();
            LocalDateTime endDate = doctorEquity.getEndDate();
            if (startDate != null
                    && LocalDateTime.now().isAfter(startDate)
                    && LocalDateTime.now().isBefore(endDate)) {
                if (type == 1) {
                    Integer orderNum = doctorEquity.getCsOrderNum() + 1;
                    doctorEquity.setCsOrderNum(orderNum);
                } else if (type == 2) {
                    LambdaQueryWrapper<ProductGiveRule> lqw = new LambdaQueryWrapper<>();
                    lqw.eq(ProductGiveRule::getType, 2)
                            .eq(ProductGiveRule::getAccountType, 2)
                            .eq(ProductGiveRule::getNumType, 2)
                            .eq(ProductGiveRule::getStatus, 1);
                    ProductGiveRule productGiveRule = productGiveRuleService.getOne(lqw);
                    //订单数量满足则累加体验时间
                    Integer csOrderNum = doctorEquity.getCsOrderNum();
                    Integer orderNum = productGiveRule.getOrderNum();
                    log.info("累计订单数:{},满足的订单数:{}", csOrderNum, orderNum);
                    if (productGiveRule != null && productGiveRule != null && csOrderNum >= orderNum) {
                        Integer num = csOrderNum / orderNum;
                        if (num > 0) {
                            Integer dayNum = productGiveRule.getNum();
                            Integer totalDay = num * dayNum;
                            Integer totalOrderNum = orderNum * num;
                            Integer csTotalDay = doctorEquity.getAccumulateDay() + totalDay;
                            log.info("乘数:{},待添加天数:{},总的天数:{},总的订单数:{},总的累计天数:{}", num,
                                    dayNum, totalDay,
                                    totalOrderNum, csTotalDay);
                            LocalDateTime doctorEquityExpirDate = doctorEquity.getExpirDate();
                            if (doctorEquityExpirDate != null) {
                                log.info("~~~添加订单延期时间~~~");
                                doctorEquity.setExpirDate(doctorEquityExpirDate.plusDays(totalDay));
                            } else {
                                doctorEquity.setExpirDate(LocalDateTime.now().plusDays(totalDay));
                            }
                            doctorEquity.setAccumulateDay(csTotalDay)
                                    .setCsOrderNum(csOrderNum - totalOrderNum).setIsReach(1)
                                    .setOrderDay(totalDay)
                                    .setOrderNum(totalOrderNum);
                        }
                    }
                }
                Boolean flag = doctorEquityService.updateById(doctorEquity);
                if (!flag) {
                    throw new ZekeException("更新失败");
                }
            }
        }
    }

    public void queryDoctorEquity() {

    }
}
